package com.yanqu.xiuxian.crosssystem.manger.elementalbonds.enums;

import com.yanqu.xiuxian.config.elementalbonds.ElementalBondsCardConfig;
import com.yanqu.xiuxian.config.elementalbonds.ElementalBondsConfigMgr;
import com.yanqu.xiuxian.config.elementalbonds.enums.*;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.data.ElementalBondsGameData;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.data.ElementalBondsPlayerData;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsBlock;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsBlockEffect;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.ElementalBondsOperateEffect;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.card.ElementalBondsCard16Color;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.card.ElementalBondsCard18X;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.entity.card.ElementalBondsCard19Color;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.logic.*;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsCardParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.param.ElementalBondsMoveParam;
import com.yanqu.xiuxian.crosssystem.manger.elementalbonds.result.ElementalBondsOperateResult;
import com.yanqu.xiuxian.server.protocol.GameErrorCode;

import java.util.*;
import java.util.stream.Collectors;

public enum ElementalBondsCardType {

    NONE(0, "无") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            return Collections.emptySet();
        }
    },

    CARD_01(1, "郑果农") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            int paramCount = elementalBondsCardConfig.getCardParamList().get(0);
            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();

            // 可使用格子
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();
            if (isGuide) {
                elementalBondsBlockSet = ElementalBondsGuideLogic.getCard01Result(blockList);
            } else {
                List<ElementalBondsBlock> allElementalBondsBlockList = new ArrayList<>();
                for (List<ElementalBondsBlock> list : blockList) {
                    for (ElementalBondsBlock elementalBondsBlock : list) {
                        if (elementalBondsBlock.getElementalBondsBlockType().getBigType().isBase()) {
                            allElementalBondsBlockList.add(elementalBondsBlock);
                        }
                    }
                }

                // 选择格子
                Collections.shuffle(allElementalBondsBlockList, random);
                for (ElementalBondsBlock elementalBondsBlock : allElementalBondsBlockList) {
                    if (elementalBondsBlockSet.size() >= paramCount) {
                        break;
                    }
                    elementalBondsBlockSet.add(elementalBondsBlock);
                }
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(elementalBondsBlockSet)));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return elementalBondsBlockSet;
        }
    },
    CARD_02(2, "啄木鸟") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 选择哪行
            int lineIndex = blockList.size() / 2;

            // 消除
            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            for (ElementalBondsBlock elementalBondsBlock : blockList.get(lineIndex)) {
                if (elementalBondsBlock.getElementalBondsBlockType().getBigType().isBase()) {
                    elementalBondsBlockSet.add(elementalBondsBlock);
                }
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(elementalBondsBlockSet)));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return elementalBondsBlockSet;
        }
    },
    CARD_03(3, "敦煌匠神") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            int paramCount = elementalBondsCardConfig.getCardParamList().get(0);

            // 统计颜色
            Map<Integer, Integer> colorCountMap = new HashMap<>();
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();
            for (List<ElementalBondsBlock> list : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : list) {
                    colorCountMap.merge(elementalBondsBlock.getColor(), 1, Integer::sum);
                }
            }

            // 找颜色数量最多的颜色
            int chooseColor = colorCountMap.entrySet()
                    .stream()
                    .filter(entry -> entry.getKey() >= ElementalBondsColorType.GREEN.getType())
                    .reduce((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? entry1 : entry2)
                    .map(Map.Entry::getKey)
                    .orElse(ElementalBondsColorType.GREEN.getType());

            // 技能不会生效到的颜色
            Set<Integer> exceptColor = new HashSet<>();
            exceptColor.add(chooseColor);
            exceptColor.add(elementalBondsCardParam.getSide() == 1 ? ElementalBondsColorType.RED.getType() : ElementalBondsColorType.BLUE.getType());

            // 可使用格子
            List<ElementalBondsBlock> allElementalBondsBlockList = new ArrayList<>();
            for (List<ElementalBondsBlock> list : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : list) {
                    if (elementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.NORMAL && !exceptColor.contains(elementalBondsBlock.getColor())) {
                        allElementalBondsBlockList.add(elementalBondsBlock);
                    }
                }
            }

            // 选择格子
            Collections.shuffle(allElementalBondsBlockList, random);
            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            for (ElementalBondsBlock elementalBondsBlock : allElementalBondsBlockList) {
                if (elementalBondsBlockSet.size() >= paramCount) {
                    break;
                }
                elementalBondsBlock.setColor(chooseColor);
                ElementalBondsSceneLogic.scene_12_checkEffectChange(elementalBondsBlock, elementalBondsGameData);
                elementalBondsBlockSet.add(elementalBondsBlock);
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(elementalBondsBlockSet), chooseColor));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return Collections.emptySet();
        }
    },
    CARD_04(4, "卞玉京") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            int paramCount = elementalBondsCardConfig.getCardParamList().get(0);

            // 可使用格子
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();
            List<ElementalBondsBlock> allElementalBondsBlockList = new ArrayList<>();
            for (List<ElementalBondsBlock> list : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : list) {
                    if (elementalBondsBlock.getElementalBondsBlockType() == ElementalBondsBlockType.NORMAL) {
                        allElementalBondsBlockList.add(elementalBondsBlock);
                    }
                }
            }

            // 选择格子
            Collections.shuffle(allElementalBondsBlockList, random);
            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            for (ElementalBondsBlock elementalBondsBlock : allElementalBondsBlockList) {
                if (elementalBondsBlockSet.size() >= paramCount) {
                    break;
                }
                int index = random.nextInt(4000) / 1000;
                elementalBondsBlock.setElementalBondsBlockType(index == 1 ? ElementalBondsBlockType.LINE_BOMB
                        : index == 2 ? ElementalBondsBlockType.COLUMN_BOMB
                        : index == 3 ? ElementalBondsBlockType.LANDMINE
                        : ElementalBondsBlockType.METEOR);
                ElementalBondsSceneLogic.scene_12_checkEffectChange(elementalBondsBlock, elementalBondsGameData);
                elementalBondsBlockSet.add(elementalBondsBlock);
            }

            // 自爆炸弹格子
            Set<ElementalBondsBlock> elementalBondsBlockSet2 = new HashSet<>();
            for (List<ElementalBondsBlock> list : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : list) {
                    if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB ||
                            elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.SPECIAL_BOMB) {
                        elementalBondsBlockSet2.add(elementalBondsBlock);
                    }
                }
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(elementalBondsBlockSet)));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, new ArrayList<>(elementalBondsBlockSet2)));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return elementalBondsBlockSet2;
        }
    },
    CARD_05(5, "捕快") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 随机位置
            int lineIndex = random.nextInt(blockList.size() - 2) + 1;
            int colIndex = random.nextInt(blockList.get(0).size() - 2) + 1;
            ElementalBondsBlock randomElementalBondsBlock = blockList.get(lineIndex).get(colIndex);

            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            List<ElementalBondsBlock> leftElementalBondsBlockList = new ArrayList<>();
            List<ElementalBondsBlock> rightElementalBondsBlockList = new ArrayList<>();

            for (List<ElementalBondsBlock> list : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : list) {
                    if (elementalBondsBlock.getElementalBondsBlockType().getBigType().isBase()) {
                        if (elementalBondsBlock.getX() != randomElementalBondsBlock.getX() && elementalBondsBlock.getY() != randomElementalBondsBlock.getY()) {
                            int subY = elementalBondsBlock.getY() - randomElementalBondsBlock.getY();
                            int subX = elementalBondsBlock.getX() - randomElementalBondsBlock.getX();
                            if (Math.abs(subY) == Math.abs(subX)) {
                                elementalBondsBlockSet.add(elementalBondsBlock);
                                if (subY * subX < 0) {
                                    leftElementalBondsBlockList.add(elementalBondsBlock);
                                } else {
                                    rightElementalBondsBlockList.add(elementalBondsBlock);
                                }
                            }
                        }
                    }
                }
            }
            elementalBondsBlockSet.add(randomElementalBondsBlock);
            leftElementalBondsBlockList.add(randomElementalBondsBlock);
            rightElementalBondsBlockList.add(randomElementalBondsBlock);

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, randomElementalBondsBlock));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 3, leftElementalBondsBlockList));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, randomElementalBondsBlock));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 3, rightElementalBondsBlockList));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return elementalBondsBlockSet;
        }
    },
    CARD_06(6, "康茶师") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<Integer> cardParamList = elementalBondsCardConfig.getCardParamList();

            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            if (ElementalBondsBlockLogic.exist(blockList, elementalBondsCardParam.getFromX(), elementalBondsCardParam.getFromY())) {
                ElementalBondsBlock elementalBondsBlock = blockList.get(elementalBondsCardParam.getFromY()).get(elementalBondsCardParam.getFromX());
                Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
                List<List<ElementalBondsBlock>> gifList = new ArrayList<>();
                List<ElementalBondsBlock> checkBlockList = new ArrayList<>();

                // 添加基础弥漫格子
                if (elementalBondsBlock.getElementalBondsBlockType().getBigType().isBase()) {
                    elementalBondsBlockSet.add(elementalBondsBlock);
                }
                gifList.add(new ArrayList<>());
                gifList.get(0).add(elementalBondsBlock);
                checkBlockList.add(elementalBondsBlock);

                // 上右下左
                int[][] xyArr = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

                // 后续弥漫
                for (int cardParam : cardParamList) {
                    List<ElementalBondsBlock> nextCheckBlockList = new ArrayList<>();
                    for (ElementalBondsBlock checkBlock : checkBlockList) {
                        for (int[] xy : xyArr) {
                            int tmpX = checkBlock.getX() + xy[0];
                            int tmpY = checkBlock.getY() + xy[1];
                            if (ElementalBondsBlockLogic.exist(blockList, tmpX, tmpY)) {
                                ElementalBondsBlock tmpBlock = blockList.get(tmpY).get(tmpX);
                                if (tmpBlock.getElementalBondsBlockType().getBigType().isBase()) {
                                    if (!elementalBondsBlockSet.contains(tmpBlock) && random.nextInt(1000) < cardParam) {
                                        nextCheckBlockList.add(tmpBlock);
                                    }
                                }
                            }
                        }
                    }
                    gifList.add(nextCheckBlockList);
                    elementalBondsBlockSet.addAll(nextCheckBlockList);
                    checkBlockList = nextCheckBlockList;
                    if (checkBlockList.isEmpty()) {
                        break;
                    }
                }

                // 技能效果
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, elementalBondsBlock));
                for (List<ElementalBondsBlock> elementalBondsBlockList : gifList) {
                    elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, elementalBondsBlockList));
                }
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 3));
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

                return elementalBondsBlockSet;
            } else {
                return Collections.emptySet();
            }
        }
    },
    CARD_07(7, "牙九") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            // 技能配置
            int chooseNum = elementalBondsCardConfig.getCardParamList().get(0);
            int maxRandomScore = 6;

            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 可随机方块
            List<ElementalBondsBlock> randomElementalBondsBlockList = new ArrayList<>();
            for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                    if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                            && elementalBondsBlock.getColor() != ElementalBondsColorType.RED.getType()
                            && elementalBondsBlock.getColor() != ElementalBondsColorType.BLUE.getType()) {
                        randomElementalBondsBlockList.add(elementalBondsBlock);
                    }
                }
            }

            // 随机方块出来
            Set<ElementalBondsBlock> chooseElementalBondsBlockSet = new HashSet<>();
            for (int i = 0; i < chooseNum && !randomElementalBondsBlockList.isEmpty(); i++) {
                int index = random.nextInt(randomElementalBondsBlockList.size());
                ElementalBondsBlock removeElementalBondsBlock = randomElementalBondsBlockList.remove(index);
                removeElementalBondsBlock.addElementalBondsBlockEffect(new ElementalBondsBlockEffect(ElementalBondsBlockEffectType.SKILL_7, random.nextInt(maxRandomScore) + 1));
                chooseElementalBondsBlockSet.add(removeElementalBondsBlock);
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(chooseElementalBondsBlockSet)));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return chooseElementalBondsBlockSet;
        }
    },
    CARD_08(8, "鲁班") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            Set<ElementalBondsBlock> movedElementalBondsBlockSet = new HashSet<>();

            for (int times = 0; times < 10; times++) { // 最多检查10轮，如果本轮没有可移动的，下面会break
                int curSize = movedElementalBondsBlockSet.size();

                for (int y = 0; y < blockList.size(); y++) {
                    for (int x = 0; x < blockList.get(y).size(); x++) {

                        ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                        if (movedElementalBondsBlockSet.contains(elementalBondsBlock)) {
                            continue;
                        }

                        // 跟右边交换
                        int rightX = x + 1;
                        if (ElementalBondsBlockLogic.exist(blockList, rightX, y) && !movedElementalBondsBlockSet.contains(blockList.get(y).get(rightX))) {
                            ElementalBondsBlock rightElementalBondsBlock = blockList.get(y).get(rightX);
                            ElementalBondsBlockLogic.exchange(blockList, x, y, rightX, y, null);
                            List<ElementalBondsBlock> elementalBondsBlockList = ElementalBondsBlockLogic.getSameColorList(blockList, elementalBondsBlock);
                            List<ElementalBondsBlock> rightElementalBondsBlockList = ElementalBondsBlockLogic.getSameColorList(blockList, rightElementalBondsBlock);
                            if (!elementalBondsBlockList.isEmpty() || !rightElementalBondsBlockList.isEmpty()) {

                                Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
                                if (!elementalBondsBlockList.isEmpty()) {
                                    elementalBondsBlockSet.addAll(elementalBondsBlockList);
                                }
                                if (!rightElementalBondsBlockList.isEmpty()) {
                                    elementalBondsBlockSet.addAll(rightElementalBondsBlockList);
                                }

                                movedElementalBondsBlockSet.addAll(elementalBondsBlockSet);
                                movedElementalBondsBlockSet.add(elementalBondsBlock);
                                movedElementalBondsBlockSet.add(rightElementalBondsBlock);

                                ElementalBondsOperateEffect elementalBondsOperateEffect = new ElementalBondsOperateEffect(this, 1);
                                elementalBondsOperateEffect.addElementalBondsBlock(elementalBondsBlock);
                                elementalBondsOperateEffect.addElementalBondsBlock(rightElementalBondsBlock);
                                elementalBondsOperateResult.addElementalBondsOperateEffect(elementalBondsOperateEffect);

                                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(ElementalBondsEffectType.HIGH_LIGHT, new ArrayList<>(elementalBondsBlockSet)));
                                continue;
                            } else {
                                ElementalBondsBlockLogic.exchange(blockList, x, y, rightX, y, null);
                            }
                        }

                        // 跟上边交换
                        int upY = y + 1;
                        if (ElementalBondsBlockLogic.exist(blockList, x, upY) && !movedElementalBondsBlockSet.contains(blockList.get(upY).get(x))) {
                            ElementalBondsBlock upElementalBondsBlock = blockList.get(upY).get(x);
                            ElementalBondsBlockLogic.exchange(blockList, x, y, x, upY, null);
                            List<ElementalBondsBlock> elementalBondsBlockList = ElementalBondsBlockLogic.getSameColorList(blockList, elementalBondsBlock);
                            List<ElementalBondsBlock> upElementalBondsBlockList = ElementalBondsBlockLogic.getSameColorList(blockList, upElementalBondsBlock);
                            if (!elementalBondsBlockList.isEmpty() || !upElementalBondsBlockList.isEmpty()) {

                                Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
                                if (!elementalBondsBlockList.isEmpty()) {
                                    elementalBondsBlockSet.addAll(elementalBondsBlockList);
                                }
                                if (!upElementalBondsBlockList.isEmpty()) {
                                    elementalBondsBlockSet.addAll(upElementalBondsBlockList);
                                }

                                movedElementalBondsBlockSet.addAll(elementalBondsBlockSet);
                                movedElementalBondsBlockSet.add(elementalBondsBlock);
                                movedElementalBondsBlockSet.add(upElementalBondsBlock);

                                ElementalBondsOperateEffect elementalBondsOperateEffect = new ElementalBondsOperateEffect(this, 1);
                                elementalBondsOperateEffect.addElementalBondsBlock(elementalBondsBlock);
                                elementalBondsOperateEffect.addElementalBondsBlock(upElementalBondsBlock);
                                elementalBondsOperateResult.addElementalBondsOperateEffect(elementalBondsOperateEffect);

                                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(ElementalBondsEffectType.HIGH_LIGHT, new ArrayList<>(elementalBondsBlockSet)));
                            } else {
                                ElementalBondsBlockLogic.exchange(blockList, x, y, x, upY, null);
                            }
                        }

                    }
                }

                if (curSize == movedElementalBondsBlockSet.size()) {
                    break;
                }
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return Collections.emptySet();
        }
    },
    CARD_09(9, "李香君") {
        @Override
        public int check(ElementalBondsGameData elementalBondsGameData, ElementalBondsCardParam elementalBondsCardParam) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();
            // 移动判断
            ElementalBondsMoveParam elementalBondsMoveParam = new ElementalBondsMoveParam(elementalBondsCardParam.getFromX(), elementalBondsCardParam.getFromY(), elementalBondsCardParam.getToX(), elementalBondsCardParam.getToY());
            int ret = ElementalBondsBlockLogic.checkExchange(blockList, elementalBondsMoveParam);
            if (ret != GameErrorCode.E_SUCCESS_VALUE) {
                return ret;
            }
            // 能否同色消除
            ElementalBondsBlockLogic.exchange(blockList, elementalBondsMoveParam, null);
            ElementalBondsBlock fromElementalBondsBlock = blockList.get(elementalBondsMoveParam.getFromY()).get(elementalBondsMoveParam.getFromX());
            ElementalBondsBlock toElementalBondsBlock = blockList.get(elementalBondsMoveParam.getToY()).get(elementalBondsMoveParam.getToX());
            if (!ElementalBondsEliminateLogic.canSameColorEliminate(blockList, fromElementalBondsBlock)
                    && !ElementalBondsEliminateLogic.canSameColorEliminate(blockList, toElementalBondsBlock)) {
                ret = GameErrorCode.E_ELEMENTAL_BONDS_CAN_NOT_ELIMINATE;
            }
            ElementalBondsBlockLogic.exchange(blockList, elementalBondsMoveParam, null);
            return ret;
        }

        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 移动
            ElementalBondsBlockLogic.exchange(elementalBondsGameData.getBlockList(), elementalBondsCardParam, elementalBondsOperateResult);

            // 获取同色消除格子
            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            for (List<ElementalBondsBlock> list : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : list) {
                    if (ElementalBondsEliminateLogic.canSameColorEliminate(blockList, elementalBondsBlock)) {
                        elementalBondsBlockSet.add(elementalBondsBlock);
                    }
                }
            }
            if (elementalBondsBlockSet.isEmpty()) {
                return Collections.emptySet();
            }

            // 消除组分类（移除触发的消除，同色的肯定是一起消除的）
            Map<Integer, Set<ElementalBondsBlock>> tmpMap = new HashMap<>(); // 按颜色分
            for (ElementalBondsBlock tmpBlock : elementalBondsBlockSet) {
                tmpMap.putIfAbsent(tmpBlock.getColor(), new HashSet<>());
                tmpMap.get(tmpBlock.getColor()).add(tmpBlock);
            }

            // 拿一下覆盖长度最长的消除组
            int maxLen = 0;
            boolean maxIsLine = false;
            Set<ElementalBondsBlock> maxSet = new HashSet<>();
            for (Set<ElementalBondsBlock> tmpSet : tmpMap.values()) {
                Set<Integer> xSet = new HashSet<>();
                Set<Integer> ySet = new HashSet<>();
                for (ElementalBondsBlock block : tmpSet) {
                    xSet.add(block.getX());
                    ySet.add(block.getY());
                }

                // 看一下横向格子多还是纵向格子多
                boolean isLine = xSet.size() > ySet.size();
                if (xSet.size() == ySet.size()) {
                    isLine = random.nextInt(1000) < 500;
                }
                int len = isLine ? xSet.size() : ySet.size();

                // 跟最大组比一下
                if (len > maxLen || len == maxLen && random.nextInt(1000) < 500) {
                    maxLen = len;
                    maxIsLine = isLine;
                    maxSet = tmpSet;
                }
            }

            // 拿消除组触发效果的格子
            Map<Integer, List<ElementalBondsBlock>> listMap = new HashMap<>(); // Map<横/纵坐标，处于该行/列的格子>
            for (ElementalBondsBlock block : maxSet) {
                int key = maxIsLine ? block.getY() : block.getX();
                listMap.putIfAbsent(key, new ArrayList<>());
                listMap.get(key).add(block);
            }
            List<ElementalBondsBlock> maxList = new ArrayList<>(); // 单行/列数量最多的list
            for (Map.Entry<Integer, List<ElementalBondsBlock>> entry : listMap.entrySet()) {
                if (entry.getValue().size() > maxList.size()) {
                    maxList = entry.getValue();
                }
            }

            // 找下触发后消除的范围
            Set<ElementalBondsBlock> firstBlockSet = new HashSet<>();
            for (ElementalBondsBlock block : maxList) {
                if (maxIsLine) {
                    for (int tempY = block.getY() - 3; tempY <= block.getY() + 3; tempY++) {
                        if (ElementalBondsBlockLogic.exist(blockList, block.getX(), tempY)) {
                            firstBlockSet.add(blockList.get(tempY).get(block.getX()));
                        }
                    }
                } else {
                    for (int tempX = block.getX() - 3; tempX <= block.getX() + 3; tempX++) {
                        if (ElementalBondsBlockLogic.exist(blockList, tempX, block.getY())) {
                            firstBlockSet.add(blockList.get(block.getY()).get(tempX));
                        }
                    }
                }
            }
            ElementalBondsBlockLogic.removeNoBaseFourBigType(firstBlockSet);

            // 技能效果(移动效果前面加了)
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, maxIsLine ? 2 : 1, maxList));// 1横向消除，2竖向消除，格子横向排列时要竖向消除
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return firstBlockSet;
        }
    },
    CARD_10(10, "寇白门") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 选择的位置
            int x = elementalBondsCardParam.getFromX();
            int y = elementalBondsCardParam.getFromY();

            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();

            if (ElementalBondsBlockLogic.exist(blockList, x, y)) {
                ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                elementalBondsBlockSet.addAll(blockList.get(y));
                for (List<ElementalBondsBlock> xElementalBondsBlockList : blockList) {
                    elementalBondsBlockSet.add(xElementalBondsBlockList.get(x));
                }
                ElementalBondsBlockLogic.removeNoBaseFourBigType(elementalBondsBlockSet);

                // 技能效果
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, elementalBondsBlock));
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(ElementalBondsEffectType.LIGHT, new ArrayList<>(elementalBondsBlockSet)));
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));
            }
            return elementalBondsBlockSet;
        }
    },
    CARD_11(11, "百戏圣刀") {
        @Override
        public int check(ElementalBondsGameData elementalBondsGameData, ElementalBondsCardParam elementalBondsCardParam) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();
            if (!ElementalBondsBlockLogic.exist(blockList, elementalBondsCardParam.getFromX(), elementalBondsCardParam.getFromY())) {
                return GameErrorCode.E_ELEMENTAL_BONDS_POS_NO_EXIST;
            }
            ElementalBondsBlock elementalBondsBlock = blockList.get(elementalBondsCardParam.getFromY()).get(elementalBondsCardParam.getFromX());
            if (elementalBondsBlock.getColor() == ElementalBondsColorType.NONE.getType()) {
                return GameErrorCode.E_ELEMENTAL_BONDS_BLOCK_NO_COLOR;
            }
            return GameErrorCode.E_SUCCESS_VALUE;
        }

        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 选择的位置
            int x = elementalBondsCardParam.getFromX();
            int y = elementalBondsCardParam.getFromY();

            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();

            if (ElementalBondsBlockLogic.exist(blockList, x, y)) {
                ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                int color = elementalBondsBlock.getColor();
                if (color != 0) {
                    // 红釉青花特殊处理
                    ElementalBondsSceneLogic.scene_08_changeColor(elementalBondsGameData, color);

                    // 消除同色
                    for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                        for (ElementalBondsBlock block : elementalBondsBlockList) {
                            if (block.getColor() == color) {
                                ElementalBondsBlockBigType elementalBondsBlockBigType = block.getElementalBondsBlockType().getBigType();
                                if (elementalBondsBlockBigType == ElementalBondsBlockBigType.NORMAL
                                        || elementalBondsBlockBigType == ElementalBondsBlockBigType.NORMAL_BOMB
                                        || elementalBondsBlockBigType == ElementalBondsBlockBigType.SPECIAL) {
                                    elementalBondsBlockSet.add(block);
                                }
                            }
                        }
                    }

                    // 技能效果
                    elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(elementalBondsBlockSet)));
                    elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));
                }
            }

            return elementalBondsBlockSet;
        }
    },
    CARD_12(12, "屠夫") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 配置
            int lineCount = elementalBondsCardConfig.getCardParamList().get(0);
            lineCount = Math.min(lineCount, blockList.size());

            // 随机取行号
            List<Integer> allIndexList = new ArrayList<>();
            for (int i = 0; i < blockList.size(); i++) {
                allIndexList.add(i);
            }
            List<Integer> chooseIndexList = new ArrayList<>();
            for (int i = 0; i < lineCount; i++) {
                int index = allIndexList.remove(random.nextInt(allIndexList.size()));
                chooseIndexList.add(index);
            }

            // 选中的格子
            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            for (int index : chooseIndexList) {
                elementalBondsBlockSet.addAll(blockList.get(index));
            }
            ElementalBondsBlockLogic.removeNoBaseFourBigType(elementalBondsBlockSet);

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(elementalBondsBlockSet)));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return elementalBondsBlockSet;
        }
    },
    CARD_13(13, "驯鹰少女") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 配置
            int paramCount = elementalBondsCardConfig.getCardParamList().get(0);

            List<ElementalBondsBlock> elementalBondsBlockList = new ArrayList<>();
            for (List<ElementalBondsBlock> list : blockList) {
                for (ElementalBondsBlock block : list) {
                    if (block.getElementalBondsBlockType().getBigType().isBase()) {
                        elementalBondsBlockList.add(block);
                    }
                }
            }

            // 选择格子
            Collections.shuffle(elementalBondsBlockList, random);
            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            for (ElementalBondsBlock block : elementalBondsBlockList) {
                if (elementalBondsBlockSet.size() >= paramCount) {
                    break;
                }
                block.addElementalBondsBlockEffect(new ElementalBondsBlockEffect(ElementalBondsBlockEffectType.SKILL_13));
                elementalBondsBlockSet.add(block);
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(ElementalBondsEffectType.UPDATE_BLOCK, new ArrayList<>(elementalBondsBlockSet)));
            if (isUseCard) { // 移动结束也会触发这个，次数不能有这个结束表现
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));
            }

            return Collections.emptySet();
        }
    },
    CARD_14(14, "紫玉") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 配置
            int moveTimes = elementalBondsCardConfig.getCardParamList().get(0);

            // 可移动格子
            int color = elementalBondsCardParam.getSide() == 1 ? ElementalBondsColorType.RED.getType() : ElementalBondsColorType.BLUE.getType();
            List<ElementalBondsBlock> moveList = new ArrayList<>();
            for (List<ElementalBondsBlock> list : blockList) {
                for (ElementalBondsBlock block : list) {
                    if (block.getColor() == color) {
                        ElementalBondsBlockBigType elementalBondsBlockBigType = block.getElementalBondsBlockType().getBigType();
                        if (elementalBondsBlockBigType == ElementalBondsBlockBigType.NORMAL
                                || elementalBondsBlockBigType == ElementalBondsBlockBigType.NORMAL_BOMB
                                || elementalBondsBlockBigType == ElementalBondsBlockBigType.SPECIAL) {
                            moveList.add(block);
                        }
                    }
                }
            }

            // 存结果
            Set<ElementalBondsBlock> allMoveSet = new HashSet<>();
            List<List<ElementalBondsBlock>> showList2 = new ArrayList<>(); // 【士】
            List<List<ElementalBondsBlock>> showList3 = new ArrayList<>(); // 【马】
            List<List<ElementalBondsBlock>> showList4 = new ArrayList<>(); // 【象】
            List<ElementalBondsBlock> needMoveList2 = new ArrayList<>();
            List<ElementalBondsBlock> needMoveList3 = new ArrayList<>();
            List<ElementalBondsBlock> needMoveList4 = new ArrayList<>();

            // 先随机变成马、象、士
            for (ElementalBondsBlock block : moveList) {
                int type = random.nextInt(3) + 2;
                if (type == 2) needMoveList2.add(block);
                if (type == 3) needMoveList3.add(block);
                if (type == 4) needMoveList4.add(block);
            }

            // 棋子移动相对坐标
            int[][] movePosArr2 = new int[][]{
                    {-1, 1}, {1, 1}, {-1, -1}, {1, -1}};
            int[][] movePosArr3 = new int[][]{
                    {-1, 2}, {1, 2}, {-2, 1}, {2, 1}, {-2, -1}, {2, -1}, {-1, -2}, {1, -2}};
            int[][] movePosArr4 = new int[][]{
                    {-2, 2}, {2, 2}, {-2, -2}, {2, -2}};

            // 开始移动
            for (int i = 0; i < moveTimes; i++) {

                // 本次移动的点，2个一组
                List<ElementalBondsBlock> curMoveList2 = new ArrayList<>();
                List<ElementalBondsBlock> curMoveList3 = new ArrayList<>();
                List<ElementalBondsBlock> curMoveList4 = new ArrayList<>();
                // 记录下次移动起始点
                List<ElementalBondsBlock> nextNeedMoveList2 = new ArrayList<>();
                List<ElementalBondsBlock> nextNeedMoveList3 = new ArrayList<>();
                List<ElementalBondsBlock> nextNeedMoveList4 = new ArrayList<>();

                // 本轮移动过的位置
                Set<ElementalBondsBlock> roundMoveSet = new HashSet<>();

                // 3马、4象、2士    按顺序移动
                ElementalBondsMoveLogic.moveChess(random, blockList, allMoveSet, needMoveList3, movePosArr3, curMoveList3, nextNeedMoveList3, roundMoveSet);
                ElementalBondsMoveLogic.moveChess(random, blockList, allMoveSet, needMoveList4, movePosArr4, curMoveList4, nextNeedMoveList4, roundMoveSet);
                ElementalBondsMoveLogic.moveChess(random, blockList, allMoveSet, needMoveList2, movePosArr2, curMoveList2, nextNeedMoveList2, roundMoveSet);

                // 记录结果
                showList2.add(curMoveList2);
                showList3.add(curMoveList3);
                showList4.add(curMoveList4);

                // 下一轮移动的
                needMoveList2 = nextNeedMoveList2;
                needMoveList3 = nextNeedMoveList3;
                needMoveList4 = nextNeedMoveList4;
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1));
            for (int i = 0; i < showList2.size(); i++) {
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, showList2.get(i)));
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 3, showList3.get(i)));
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 4, showList4.get(i)));
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 5));
            }
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return allMoveSet;
        }
    },
    CARD_15(15, "沈万三") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 取颜色数量
            int colorCount = elementalBondsCardConfig.getCardParamList().get(0);

            // 取红色、蓝色外的颜色，打乱
            List<Integer> colorList = Arrays.stream(ElementalBondsColorType.values())
                    .filter(elementalBondsColorType ->
                            elementalBondsColorType != ElementalBondsColorType.NONE
                                    && elementalBondsColorType != ElementalBondsColorType.RED
                                    && elementalBondsColorType != ElementalBondsColorType.BLUE)
                    .map(ElementalBondsColorType::getType)
                    .collect(Collectors.toList());
            Collections.shuffle(colorList, random);

            // 拿随机到的颜色
            Set<Integer> colorSet = new HashSet<>();
            for (Integer color : colorList) {
                if (colorSet.size() < colorCount) {
                    colorSet.add(color);
                }
            }

            // 拿消除的方块
            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                    if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                            && colorSet.contains(elementalBondsBlock.getColor())) {
                        elementalBondsBlockSet.add(elementalBondsBlock);
                    }
                }
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(elementalBondsBlockSet)));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return elementalBondsBlockSet;
        }
    },
    CARD_16(16, "马湘兰") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 【自动选颜色】
            List<ElementalBondsCard16Color> elementalBondsCard16ColorList = new ArrayList<>();
            ElementalBondsColorType skipElementalBondsColorType = elementalBondsCardParam.getSide() == 1 ? ElementalBondsColorType.RED : ElementalBondsColorType.BLUE;
            for (ElementalBondsColorType elementalBondsColorType : ElementalBondsColorType.values()) {
                // 跳过的颜色
                if (elementalBondsColorType == ElementalBondsColorType.NONE || elementalBondsColorType == skipElementalBondsColorType) {
                    continue;
                }
                // 每种颜色看看多少4连，能变色多少个
                int bombNum = 0;
                int sumSubValue = 0;
                for (int x = 0; x < blockList.get(0).size(); x++) {
                    int topY = 0;
                    int bottomY = blockList.size() - 1;
                    // 从下往上找
                    for (int y = 0; y < blockList.size(); y++) {
                        ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                        if (elementalBondsBlock.getColor() == elementalBondsColorType.getType()) {
                            if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                                    || elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {
                                bottomY = y;
                                break;
                            }
                        }
                    }
                    // 从上往下找
                    for (int y = blockList.size() - 1; y >= 0; y--) {
                        ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                        if (elementalBondsBlock.getColor() == elementalBondsColorType.getType()) {
                            if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                                    || elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {
                                topY = y;
                                break;
                            }
                        }
                    }
                    int subValue = topY - bottomY;
                    if (subValue >= 3) {
                        bombNum++;
                    }
                    if (subValue > 0) {
                        sumSubValue += subValue;
                    }
                }
                elementalBondsCard16ColorList.add(new ElementalBondsCard16Color(elementalBondsColorType.getType(), bombNum, sumSubValue));
            }

            Optional<ElementalBondsCard16Color> firstOptional = elementalBondsCard16ColorList.stream().min((o1, o2) -> {
                if (o2.getBombNum() != o1.getBombNum()) {
                    return Integer.compare(o2.getBombNum(), o1.getBombNum());
                }
                if (o2.getSumSubValue() != o1.getSumSubValue()) {
                    return Integer.compare(o2.getSumSubValue(), o1.getSumSubValue());
                }
                return Integer.compare(o2.getColorWeight(), o1.getColorWeight());
            });
            Set<ElementalBondsBlock> returnElementalBondsBlockSet = new HashSet<>();
            if (firstOptional.isPresent()) {
                int color = firstOptional.get().getColor();
                Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
                for (int x = 0; x < blockList.get(0).size(); x++) {
                    int topY = -1;
                    for (int y = blockList.size() - 1; y >= 0; y--) {
                        ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                        if (elementalBondsBlock.getColor() == color) {
                            if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                                    || elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {
                                topY = elementalBondsBlock.getY();
                                break;
                            }
                        }
                    }
                    int bottomY = blockList.size();
                    for (int y = 0; y < blockList.size(); y++) {
                        ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                        if (elementalBondsBlock.getColor() == color) {
                            if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                                    || elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {
                                bottomY = elementalBondsBlock.getY();
                                break;
                            }
                        }
                    }
                    if (bottomY < topY) {
                        elementalBondsBlockSet.add(blockList.get(bottomY).get(x));
                        elementalBondsBlockSet.add(blockList.get(topY).get(x));
                    }
                    for (int y = bottomY + 1; y < topY; y++) {
                        ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                        if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                                || elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {
                            elementalBondsBlock.setColor(color);
                            ElementalBondsSceneLogic.scene_12_checkEffectChange(elementalBondsBlock, elementalBondsGameData);
                            elementalBondsBlockSet.add(elementalBondsBlock);
                        }
                    }
                }
                // 技能效果
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(elementalBondsBlockSet)));
                // 消除
                ElementalBondsEliminateLogic.bigEliminate(elementalBondsGameData, elementalBondsPlayerData, null,
                        new HashSet<>(), elementalBondsOperateResult, random, -1, roomRound, turnPlayer);

                // 随机一个炸弹爆炸
                List<ElementalBondsBlock> bombElementalBondsBlockList = new ArrayList<>();
                for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                    for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                        if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {
                            bombElementalBondsBlockList.add(elementalBondsBlock);
                        }
                    }
                }
                ElementalBondsBlock elementalBondsBlock = null;
                if (!bombElementalBondsBlockList.isEmpty()) {
                    elementalBondsBlock = bombElementalBondsBlockList.get(random.nextInt(bombElementalBondsBlockList.size()));
                    elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, elementalBondsBlock));
                }
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

                if (elementalBondsBlock != null) {
                    returnElementalBondsBlockSet.add(elementalBondsBlock);
                }
            }
            return returnElementalBondsBlockSet;
        }
    },
    CARD_17(17, "方火头") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 配置
            int createNum = elementalBondsCardConfig.getCardParamList().get(0);
            int bombNum = elementalBondsCardConfig.getCardParamList().get(1);

            // 所有可用格子
            List<ElementalBondsBlock> elementalBondsBlockList = new ArrayList<>();
            for (List<ElementalBondsBlock> elementalBondsBlocks : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlocks) {
                    if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL) {
                        elementalBondsBlockList.add(elementalBondsBlock);
                    }
                }
            }

            List<ElementalBondsBlock> replaceList = new ArrayList<>();
            List<ElementalBondsBlock> bombList = new ArrayList<>();
            for (int i = 0; i < createNum; i++) {
                ElementalBondsBlock elementalBondsBlock = elementalBondsBlockList.remove(random.nextInt(elementalBondsBlockList.size()));

                elementalBondsBlock.setElementalBondsBlockType(ElementalBondsBlockType.ROCKET);
                ElementalBondsSceneLogic.scene_12_checkEffectChange(elementalBondsBlock, elementalBondsGameData);
                elementalBondsBlock.setElementalBondsDirectionType(ElementalBondsDirectionType.getRandomType(random));

                replaceList.add(elementalBondsBlock);
                if (bombList.size() < bombNum) {
                    bombList.add(elementalBondsBlock);
                }
            }

            // 技能效果
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, replaceList));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, bombList));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return new HashSet<>(bombList);
        }
    },
    CARD_18(18, "毕昇") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            int chooseColNum = 3;

            // 统计每列普通炸弹
            Map<Integer, ElementalBondsCard18X> elementalBondsCard18XMap = new HashMap<>();
            for (int x = 0; x < ElementalBondsConfigMgr.getInstance().getBlockListWidth(); x++) {
                elementalBondsCard18XMap.put(x, new ElementalBondsCard18X(x));
            }
            for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                    if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {
                        ElementalBondsCard18X elementalBondsCard18X = elementalBondsCard18XMap.get(elementalBondsBlock.getX());
                        elementalBondsCard18X.incrementNum();
                    }
                }
            }
            List<ElementalBondsCard18X> elementalBondsCard18XList = new ArrayList<>(elementalBondsCard18XMap.values());
            Collections.shuffle(elementalBondsCard18XList, random);
            elementalBondsCard18XList.sort(Comparator.comparingInt(ElementalBondsCard18X::getNum).reversed());

            // 抽几个出来
            List<Integer> chooseList = new ArrayList<>();
            for (int loop = 0; loop < 99 && chooseList.size() < chooseColNum && !elementalBondsCard18XList.isEmpty(); loop++) {

                List<ElementalBondsCard18X> sameNumList = new ArrayList<>();
                int num = elementalBondsCard18XList.get(0).getNum();
                for (ElementalBondsCard18X elementalBondsCard18X : elementalBondsCard18XList) {
                    if (elementalBondsCard18X.getNum() == num) {
                        sameNumList.add(elementalBondsCard18X);
                    } else {
                        break;
                    }
                }

                int chooseX = sameNumList.get(random.nextInt(sameNumList.size())).getX();
                chooseList.add(chooseX);

                for (int i = 0; i < elementalBondsCard18XList.size(); i++) {
                    int tmpX = elementalBondsCard18XList.get(i).getX();
                    if (Math.abs(tmpX - chooseX) <= 1) { // 移除自己，移除相邻两列
                        elementalBondsCard18XList.remove(i--);
                    }
                }
            }
            chooseList.sort(Comparator.comparing(Integer::intValue));

            // 方向
            List<Integer> directionList = new ArrayList<>();
            for (int i = 0; i < chooseList.size(); i++) { // 初始化一个0
                directionList.add(0);
            }
            if (chooseList.get(0) == 0) { // 特殊情况先处理
                directionList.set(0, 1);
            }
            if (chooseList.get(chooseList.size() - 1) == ElementalBondsConfigMgr.getInstance().getBlockListWidth() - 1) {
                directionList.set(chooseList.size() - 1, -1);
            }
            Set<Integer> noSet = new HashSet<>();
            for (int i = 0; i < chooseList.size(); i++) { // 记录无法选中的x值
                int choose = chooseList.get(i);
                noSet.add(choose);

                int direction = directionList.get(i);
                if (direction != 0) {
                    noSet.add(choose + direction);
                }
            }
            for (int order = 0; order < 2; order++) { // 0处理左右两边间隔1位[都]有占用的，1处理其余的
                for (int i = 0; i < directionList.size(); i++) {
                    int direction = directionList.get(i);
                    if (direction != 0) { // 已有方向，跳过
                        continue;
                    }
                    int x = chooseList.get(i);
                    if (order == 0) {
                        if (i != 0 && i != chooseList.size() - 1
                                && chooseList.get(i - 1) == x - 2 && chooseList.get(i + 1) == x + 2) {
                            // 第一次处理，只处理中间列、且两边间隔1列都有占用的列
                        } else {
                            continue;
                        }
                    }
                    if (noSet.contains(x - 1)) { // 左边不能选，选右
                        direction = 1;
                    } else if (noSet.contains(x + 1)) { // 右边不能选，选左
                        direction = -1;
                    } else { // 随机
                        direction = random.nextInt(1000) >= 500 ? 1 : -1;
                    }
                    directionList.set(i, direction);
                    noSet.add(x + direction);
                }
            }

            // 复制开始
            List<ElementalBondsBlock> leftElementalBondsBlockList = new ArrayList<>();
            List<ElementalBondsBlock> rightElementalBondsBlockList = new ArrayList<>();
            for (int i = 0; i < chooseList.size(); i++) {
                for (int y = 0; y < blockList.size(); y++) {

                    ElementalBondsBlock baseBlock = blockList.get(y).get(chooseList.get(i));
                    if (baseBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                            || baseBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {

                        int direction = directionList.get(i);
                        int copyX = baseBlock.getX() + direction;
                        ElementalBondsBlock replacePos = blockList.get(y).get(copyX);
                        if (replacePos.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                                || replacePos.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {

                            ElementalBondsBlock clone = baseBlock.clone();
                            clone.setElementalBondsBlockEffectList(new ArrayList<>()); // 效果不能复制
                            clone.setX(copyX);
                            clone.setY(y);
                            blockList.get(y).set(copyX, clone);

                            ElementalBondsBlock tmp = baseBlock.clone();
                            tmp.setElementalBondsBlockEffectList(new ArrayList<>()); // 给个假效果
                            if (direction == 1) {
                                rightElementalBondsBlockList.add(tmp);
                            } else {
                                leftElementalBondsBlockList.add(tmp);
                            }
                        }
                    }
                }
            }

            // 技能效果
            if (!rightElementalBondsBlockList.isEmpty()) {
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, rightElementalBondsBlockList));
            }
            if (!leftElementalBondsBlockList.isEmpty()) {
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, leftElementalBondsBlockList));
            }
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return Collections.emptySet();
        }
    },
    CARD_19(19, "丁戏人") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 颜色数量
            int chooseColorCount = 2;

            // 写死顺序
            // 42 43 44 45 46 47 48
            // 35 36 37 38 39 40 41
            // 28 29 30 31 32 33 34
            // 21 22 23 24 25 26 27
            // 14 15 16 17 18 19 20
            // 07 08 09 10 11 12 13
            // 00 01 02 03 04 05 06
            // 颜色1：45, 44, 46, 38, 37, 39, 31, 43, 47, 36, 30, 40, 32, 24, 17, 10, 3
            // 颜色2：21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 3
            // 颜色3：27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3
            int[][] posArrs = new int[][]{
                    // {45, 44, 46, 38, 37, 39, 31, 43, 47, 36, 30, 40, 32, 24, 17, 10, 3, 21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 3, 27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3},
                    // {27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3, 45, 44, 46, 38, 37, 39, 31, 43, 47, 36, 30, 40, 32, 24, 17, 10, 3, 21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 3},
                    // {21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 3, 27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3, 45, 44, 46, 38, 37, 39, 31, 43, 47, 36, 30, 40, 32, 24, 17, 10, 3},
                    {27, 34, 20, 26, 33, 19, 25, 41, 13, 12, 18, 6, 48, 5, 11, 4, 3, 10, 17, 24, 32, 40, 39, 47, 46, 31, 38, 45, 30, 37, 44, 36, 43, 2, 9, 1, 42, 0, 16, 8, 7, 35, 23, 15, 29, 22, 14, 28, 21},
                    {21, 28, 14, 22, 29, 15, 23, 35, 7, 8, 16, 0, 42, 1, 9, 2, 30, 36, 37, 43, 44, 31, 38, 45, 32, 39, 46, 40, 47, 24, 17, 10, 3, 4, 11, 5, 48, 6, 18, 12, 13, 41, 25, 19, 33, 26, 20, 34, 27},
            };

            // 统计方块数量最多的颜色
            Map<Integer, ElementalBondsCard19Color> elementalBondsCard19ColorMap = new HashMap<>();
            for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                    int color = elementalBondsBlock.getColor();
                    elementalBondsCard19ColorMap.putIfAbsent(color, new ElementalBondsCard19Color(color));
                    ElementalBondsCard19Color elementalBondsCard19Color = elementalBondsCard19ColorMap.get(color);
                    elementalBondsCard19Color.incrementNum();
                }
            }
            elementalBondsCard19ColorMap.remove(ElementalBondsColorType.NONE.getType());
            List<ElementalBondsCard19Color> elementalBondsCard19ColorList = new ArrayList<>(elementalBondsCard19ColorMap.values());
            Collections.shuffle(elementalBondsCard19ColorList, random);
            elementalBondsCard19ColorList.sort(Comparator.comparingInt(ElementalBondsCard19Color::getNum).reversed());

            // 获取颜色
            List<Integer> chooseColorList = new ArrayList<>();
            for (int i = 0; i < chooseColorCount && i < elementalBondsCard19ColorList.size(); i++) {
                chooseColorList.add(elementalBondsCard19ColorList.get(i).getColor());
            }

            // 记录移动总结果
            List<List<ElementalBondsBlock>> allMoveList = new ArrayList<>();
            List<List<ElementalBondsBlock>> allLightList = new ArrayList<>();
            for (int i = 0; i < chooseColorList.size(); i++) {
                int color = chooseColorList.get(i);

                // 找需要移动的格子，有序
                List<ElementalBondsBlock> needMoveList = new ArrayList<>();
                for (int y = blockList.size() - 1; y >= 0; y--) {
                    for (int x = 0; x < blockList.get(y).size(); x++) {
                        ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                        if (elementalBondsBlock.getColor() == color) {
                            if (elementalBondsBlock.getElementalBondsBlockType().getBigType().isBase()) {
                                needMoveList.add(elementalBondsBlock);
                            }
                        }
                    }
                }
                allLightList.add(new ArrayList<>(needMoveList));

                // 被移动的格子，有序
                List<ElementalBondsBlock> beMoveList = new ArrayList<>();
                Set<Integer> posSet = new HashSet<>();
                int[] posArr = posArrs[i];
                for (int j = 0; j < needMoveList.size(); j++) {
                    int pos = posArr[j];
                    posSet.add(pos);
                    beMoveList.add(ElementalBondsBlockLogic.getBlock(blockList, pos));
                }

                List<ElementalBondsBlock> moveList = new ArrayList<>();

                // 主动移动
                for (int j = 0; j < needMoveList.size(); j++) {
                    ElementalBondsBlock from = needMoveList.get(j);
                    ElementalBondsBlock fromClone = from.clone();
                    ElementalBondsBlock to = beMoveList.get(j);

                    fromClone.setX(to.getX());
                    fromClone.setY(to.getY());
                    blockList.get(fromClone.getY()).set(fromClone.getX(), fromClone);
                    moveList.add(from);
                    moveList.add(fromClone);
                }

                // 被动移动
                Collections.shuffle(needMoveList, random);
                int index = 0;
                for (ElementalBondsBlock to : beMoveList) {
                    if (to.getColor() == color) {
                        continue;
                    }
                    while (posSet.contains(ElementalBondsBlockLogic.getPos(blockList, needMoveList.get(index)))) {
                        index++;
                    }
                    ElementalBondsBlock from = needMoveList.get(index);

                    ElementalBondsBlock toClone = to.clone();
                    toClone.setX(from.getX());
                    toClone.setY(from.getY());
                    blockList.get(toClone.getY()).set(toClone.getX(), toClone);
                    moveList.add(to);
                    moveList.add(toClone);
                    index++;
                }

                allMoveList.add(moveList);
            }

            // 技能效果
            for (int i = 0; i < chooseColorList.size(); i++) {

                List<ElementalBondsBlock> moveList = allMoveList.get(i);
                List<ElementalBondsBlock> lightList = allLightList.get(i);

                List<ElementalBondsBlock> elementalBondsBlockList1 = new ArrayList<>(lightList);
                List<ElementalBondsBlock> elementalBondsBlockList2 = new ArrayList<>();
                for (int j = 0; j < moveList.size() - 1; j += 2) {
                    elementalBondsBlockList2.add(moveList.get(j));
                    elementalBondsBlockList2.add(moveList.get(j + 1));
                }
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, elementalBondsBlockList1));
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, elementalBondsBlockList2, i + 2));
            }
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return Collections.emptySet();
        }
    },
    CARD_20(20, "花艺师") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 写死三种颜色
            int chooseColorCount = 3;

            // 随机三个颜色
            List<Integer> colorList = new ArrayList<>();
            List<Integer> chooseColorList = new ArrayList<>();
            for (ElementalBondsColorType elementalBondsColorType : ElementalBondsColorType.values()) {
                if (elementalBondsColorType != ElementalBondsColorType.NONE
                        && elementalBondsColorType != ElementalBondsColorType.RED
                        && elementalBondsColorType != ElementalBondsColorType.BLUE) {
                    colorList.add(elementalBondsColorType.getType());
                }
            }
            for (int i = 0; i < chooseColorCount && !colorList.isEmpty(); i++) {
                int color = colorList.remove(random.nextInt(colorList.size()));
                chooseColorList.add(color);
            }

            // 变色+消除
            for (int i = 0; i < chooseColorList.size() - 1; i++) {
                int baseColor = chooseColorList.get(i);
                int toColor = chooseColorList.get(i + 1);

                Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
                for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                    for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                        if (elementalBondsBlock.getColor() == baseColor) {
                            if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL
                                    || elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL_BOMB) {
                                ElementalBondsBlock clone = elementalBondsBlock.clone();
                                clone.setColor(toColor);
                                ElementalBondsSceneLogic.scene_12_checkEffectChange(clone, elementalBondsGameData);
                                blockList.get(clone.getY()).set(clone.getX(), clone);
                                elementalBondsBlockSet.add(clone);
                            }
                        }
                    }
                }

                // 技能效果
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, new ArrayList<>(elementalBondsBlockSet), baseColor));
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, new ArrayList<>(elementalBondsBlockSet), toColor));
                // 消除
                if (i < chooseColorList.size() - 1) {
                    ElementalBondsEliminateLogic.bigEliminate(elementalBondsGameData, elementalBondsPlayerData, null,
                            new HashSet<>(), elementalBondsOperateResult, random, -1, roomRound, turnPlayer);
                }
            }
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return Collections.emptySet();
        }
    },
    CARD_21(21, "李神手") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 配置
            int count = elementalBondsCardConfig.getCardParamList().get(0);

            // 可选择方块
            Set<Integer> colorSet = new HashSet<>();
            List<ElementalBondsBlock> elementalBondsBlockList = new ArrayList<>();
            for (int y = 1; y < blockList.size() - 1; y++) {
                for (int x = 1; x < blockList.get(y).size() - 1; x++) {
                    ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                    int color = elementalBondsBlock.getColor();
                    if (color != ElementalBondsColorType.NONE.getType()
                            && color != ElementalBondsColorType.RED.getType()
                            && color != ElementalBondsColorType.BLUE.getType()) {
                        if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL) {
                            elementalBondsBlockList.add(elementalBondsBlock);
                            colorSet.add(color);
                        }
                    }
                }
            }

            // 统计可选颜色
            ArrayList<Integer> colorList = new ArrayList<>(colorSet);

            // 随机选方块
            List<ElementalBondsBlock> paperFlowerList = new ArrayList<>();
            List<List<ElementalBondsBlock>> allBombList = new ArrayList<>();
            for (int i = 0; i < count; i++) {

                // 本次随机可选
                List<ElementalBondsBlock> randomElementalBondsBlockList = new ArrayList<>();
                if (!colorList.isEmpty()) { // 尽量不同种颜色都来一个
                    int color = colorList.remove(random.nextInt(colorList.size()));
                    for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                        if (elementalBondsBlock.getColor() == color) {
                            randomElementalBondsBlockList.add(elementalBondsBlock);
                        }
                    }
                }
                if (randomElementalBondsBlockList.isEmpty()) {
                    randomElementalBondsBlockList = elementalBondsBlockList;
                }
                if (randomElementalBondsBlockList.isEmpty()) {
                    break;
                }

                // 随机方块
                ElementalBondsBlock randomElementalBondsBlock = randomElementalBondsBlockList.remove(random.nextInt(randomElementalBondsBlockList.size()));
                elementalBondsBlockList.remove(randomElementalBondsBlock);

                // 替换窗花
                randomElementalBondsBlock.setElementalBondsBlockType(ElementalBondsBlockType.PAPER_FLOWER);
                ElementalBondsSceneLogic.scene_12_checkEffectChange(randomElementalBondsBlock, elementalBondsGameData);

                // 计算爆炸效果
                List<ElementalBondsBlock> bombList = new ArrayList<>();
                bombList.add(randomElementalBondsBlock);

                int x = randomElementalBondsBlock.getX();
                int y = randomElementalBondsBlock.getY();
                List<ElementalBondsBlock> existList = new ArrayList<>();
                if (ElementalBondsBlockLogic.exist(blockList, x, y + 1)) existList.add(blockList.get(y + 1).get(x));
                if (ElementalBondsBlockLogic.exist(blockList, x + 1, y)) existList.add(blockList.get(y).get(x + 1));
                if (ElementalBondsBlockLogic.exist(blockList, x, y - 1)) existList.add(blockList.get(y - 1).get(x));
                if (ElementalBondsBlockLogic.exist(blockList, x - 1, y)) existList.add(blockList.get(y).get(x - 1));
                for (ElementalBondsBlock tmpBlock : existList) {
                    if (tmpBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL) {
                        bombList.add(tmpBlock);
                    }
                    elementalBondsBlockList.remove(tmpBlock);
                }

                // 添加结果
                paperFlowerList.add(randomElementalBondsBlock);
                allBombList.add(bombList);
            }

            // 技能效果
            for (List<ElementalBondsBlock> bombList : allBombList) {
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, bombList, bombList.get(0).getColor()));
            }
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            // 随机一个小窗花消除
            ElementalBondsBlock chooseBlock = null;
            if (!paperFlowerList.isEmpty()) {
                int randomIndex = random.nextInt(paperFlowerList.size());
                chooseBlock = paperFlowerList.get(randomIndex);
            }

            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            for (List<ElementalBondsBlock> bombList : allBombList) {
                elementalBondsBlockSet.addAll(bombList.subList(1, bombList.size()));
            }
            if (chooseBlock != null) {
                elementalBondsBlockSet.add(chooseBlock);
            }

            return elementalBondsBlockSet;
        }
    },
    CARD_22(22, "活阎王") {
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 配置
            int count = elementalBondsCardConfig.getCardParamList().get(0);

            // 可选方块
            List<ElementalBondsBlock> allElementalBondsBlockList = new ArrayList<>();
            List<ElementalBondsBlock> cardElementalBondsBlockList = new ArrayList<>();
            for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                    if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL) {
                        boolean cardElementalBondsBlock = false;
                        for (ElementalBondsBlockEffect elementalBondsBlockEffect : elementalBondsBlock.getElementalBondsBlockEffectList()) {
                            if (elementalBondsBlockEffect.getEffectType() == ElementalBondsBlockEffectType.SKILL_22) {
                                cardElementalBondsBlock = true;
                                elementalBondsBlockEffect.setTimes(0);// 有恶魔方块要重置次数
                                break;
                            }
                        }
                        if (cardElementalBondsBlock) {
                            cardElementalBondsBlockList.add(elementalBondsBlock);
                        } else {
                            allElementalBondsBlockList.add(elementalBondsBlock);
                        }
                    }
                }
            }

            // 打乱
            Collections.shuffle(allElementalBondsBlockList, random);

            // 抽几个格子标记
            long createCount = count - cardElementalBondsBlockList.size();
            if (createCount > 0) {
                List<ElementalBondsBlock> elementalBondsBlockList = new ArrayList<>();
                for (int i = 0; i < createCount && i < allElementalBondsBlockList.size(); i++) { // 补充满

                    ElementalBondsBlockEffect elementalBondsBlockEffect = new ElementalBondsBlockEffect(ElementalBondsBlockEffectType.SKILL_22);
                    elementalBondsBlockEffect.setEffectValue(random.nextInt(3) + 1); // 1、2、3对应Y、X、十字

                    ElementalBondsBlock elementalBondsBlock = allElementalBondsBlockList.get(i);
                    elementalBondsBlock.addElementalBondsBlockEffect(elementalBondsBlockEffect);

                    elementalBondsBlockList.add(elementalBondsBlock);
                    cardElementalBondsBlockList.add(elementalBondsBlock);
                }
                elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, elementalBondsBlockList));
            }

            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return new HashSet<>(cardElementalBondsBlockList);
        }
    },
    CARD_23(23, "手工少女") {
        /**
         * 手工少女
         * 1: 丢宝箱   宝箱位置
         * 2: 吸收    第一个格子是机巧盒  后面的是被吸收的格子
         * 3: 放出炸弹     第一个格子是机巧盒  后面的是炸弹格子
         */
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 找机巧盒位置, 先判断有没有机巧盒
            ElementalBondsBlock smartBoxBlock = ElementalBondsBlockLogic.getSmartBoxBlock(blockList);
            if (smartBoxBlock == null) {
                // 固定顺序 y:0->6  x: 3, 2, 4, 1, 5, 0, 6
                int[] xArr = new int[]{3, 2, 4, 1, 5, 0, 6};
                boolean isFind = false;
                for (int x : xArr) {
                    if (isFind) {
                        break;
                    }
                    for (int y = 0; y < 7; y++) {
                        if (isFind) {
                            break;
                        }
                        ElementalBondsBlock elementalBondsBlock = blockList.get(y).get(x);
                        if (elementalBondsBlock == null || elementalBondsBlock.getElementalBondsBlockType() != ElementalBondsBlockType.NORMAL) {
                            continue;
                        }
                        // 替换成机巧盒
                        elementalBondsBlock.setElementalBondsBlockType(ElementalBondsBlockType.SMART_BOX);
                        elementalBondsBlock.setColor(ElementalBondsColorType.NONE.getType());
                        elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, elementalBondsBlock));
                        isFind = true;
                        smartBoxBlock = elementalBondsBlock;
                    }
                }
            }

            // 随机吸n个颜色（先保证有）
            int colorNum = elementalBondsCardConfig.getCardParamList().get(0);
            Set<Integer> colorSet = new HashSet<>();
            for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                    if (elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL) {
                        int color = elementalBondsBlock.getColor();
                        if (color != ElementalBondsColorType.NONE.getType()
                                && color != ElementalBondsColorType.RED.getType()
                                && color != ElementalBondsColorType.BLUE.getType()) {
                            colorSet.add(color);
                        }
                    }
                }
            }
            List<Integer> colorList = new ArrayList<>(colorSet);
            List<Integer> chooseList = new ArrayList<>();
            for (int i = 0; i < colorNum; i++) {
                if (!colorList.isEmpty()) {
                    chooseList.add(colorList.remove(random.nextInt(colorList.size())));
                } else {
                    break;
                }
            }
            // 获取消除格子
            Set<ElementalBondsBlock> elementalBondsBlockSet = new HashSet<>();
            for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                    if (chooseList.contains(elementalBondsBlock.getColor())
                            && elementalBondsBlock.getElementalBondsBlockType().getBigType() == ElementalBondsBlockBigType.NORMAL) {
                        elementalBondsBlockSet.add(elementalBondsBlock);
                    }
                }
            }

            // 技能效果
            List<ElementalBondsBlock> elementalBondsBlockList = new ArrayList<>();
            if (smartBoxBlock != null) {
                elementalBondsBlockList.add(smartBoxBlock);
            }
            elementalBondsBlockList.addAll(elementalBondsBlockSet);
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 2, elementalBondsBlockList));
            elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));

            return elementalBondsBlockSet;
        }
    },
    CARD_24(24, "张三丰") {
        @Override
        public int check(ElementalBondsGameData elementalBondsGameData, ElementalBondsCardParam elementalBondsCardParam) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();
            if (!ElementalBondsBlockLogic.exist(blockList, elementalBondsCardParam.getFromX(), elementalBondsCardParam.getFromY())) {
                return GameErrorCode.E_ELEMENTAL_BONDS_POS_NO_EXIST;
            }
            ElementalBondsBlock elementalBondsBlock = blockList.get(elementalBondsCardParam.getFromY()).get(elementalBondsCardParam.getFromX());
            if (elementalBondsBlock.getColor() == ElementalBondsColorType.NONE.getType()) {
                return GameErrorCode.E_ELEMENTAL_BONDS_BLOCK_NO_COLOR;
            }
            return GameErrorCode.E_SUCCESS_VALUE;
        }

        /**
         * 张三丰
         * 1: 移动  [格子1，被替换的格子1，格子2，被替换的格子2 。。。。]
         * param 1: 向上 2、向下 3、向左 4、向右
         */
        @Override
        public Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                            ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                            Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard) {
            List<List<ElementalBondsBlock>> blockList = elementalBondsGameData.getBlockList();

            // 选择的位置
            int x = elementalBondsCardParam.getFromX();
            int y = elementalBondsCardParam.getFromY();

            if (ElementalBondsBlockLogic.exist(blockList, x, y)) {
                ElementalBondsBlock chooseElementalBondsBlock = blockList.get(y).get(x);
                int color = chooseElementalBondsBlock.getColor();
                if (color > 0) {
                    Set<ElementalBondsBlock> ElementalBondsBlockSet = new HashSet<>();
                    for (List<ElementalBondsBlock> elementalBondsBlockList : blockList) {
                        for (ElementalBondsBlock elementalBondsBlock : elementalBondsBlockList) {
                            if (elementalBondsBlock.getColor() == color) {
                                ElementalBondsBlockSet.add(elementalBondsBlock.clone());
                            }
                        }
                    }

                    // 开始打太极
                    // 上下左右
                    int[][] dirs = new int[][]{{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
                    for (int i = 0; i < dirs.length; i++) {
                        List<ElementalBondsBlock> elementalBondsBlockList = new ArrayList<>();
                        for (ElementalBondsBlock elementalBondsBlock : ElementalBondsBlockSet) {
                            if (ElementalBondsBlockLogic.exist(blockList, elementalBondsBlock.getX() + dirs[i][0], elementalBondsBlock.getY() + dirs[i][1])) {
                                ElementalBondsBlock targetElementalBondsBlock = blockList.get(elementalBondsBlock.getY() + dirs[i][1]).get(elementalBondsBlock.getX() + dirs[i][0]);
                                if (targetElementalBondsBlock.getElementalBondsBlockType().getBigType() != ElementalBondsBlockBigType.NORMAL
                                        && targetElementalBondsBlock.getElementalBondsBlockType().getBigType() != ElementalBondsBlockBigType.NORMAL_BOMB) {
                                    continue;
                                }
                                targetElementalBondsBlock.setColor(color);
                                elementalBondsBlockList.add(elementalBondsBlock.clone());
                                elementalBondsBlockList.add(targetElementalBondsBlock.clone());
                            } else {
                                // 不存在的格子
                                elementalBondsBlockList.add(elementalBondsBlock.clone());
                                ElementalBondsBlock clone = elementalBondsBlock.clone();
                                clone.setX(elementalBondsBlock.getX() + dirs[i][0]);
                                clone.setY(elementalBondsBlock.getY() + dirs[i][1]);
                                elementalBondsBlockList.add(clone);
                            }
                        }
                        elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 1, elementalBondsBlockList, i + 1));
                    }
                    elementalBondsOperateResult.addElementalBondsOperateEffect(new ElementalBondsOperateEffect(this, 0));
                }
            }

            return Collections.emptySet();
        }
    },
    ;

    private final int type;
    private final String desc;

    ElementalBondsCardType(int type, String desc) {
        this.type = type;
        this.desc = desc;
    }

    public static ElementalBondsCardType forType(int type) {
        return Arrays.stream(ElementalBondsCardType.values())
                .filter(elementalBondsCardType -> elementalBondsCardType.getType() == type)
                .findFirst()
                .orElse(NONE);
    }

    public int getType() {
        return type;
    }

    public String getDesc() {
        return desc;
    }

    public int check(ElementalBondsGameData elementalBondsGameData, ElementalBondsCardParam elementalBondsCardParam) {
        return GameErrorCode.E_SUCCESS_VALUE;
    }

    public abstract Set<ElementalBondsBlock> use(ElementalBondsCardConfig elementalBondsCardConfig, ElementalBondsCardParam elementalBondsCardParam,
                                                 ElementalBondsGameData elementalBondsGameData, ElementalBondsOperateResult elementalBondsOperateResult, ElementalBondsPlayerData elementalBondsPlayerData,
                                                 Random random, boolean isGuide, int roomRound, int turnPlayer, boolean isUseCard);

}
